﻿#region Licence
// <copyright file="SampleModule/AccueilAppelsViewModel.cs" company="Kopigi">
// Copyright © Kopigi 2014
// </copyright>
// ****************************************************************************
// <author>Marc PLESSIS</author>
// <date>26/10/2014</date>
// <project>Nentang.wpf</project>
// <web>http://nentang.codeplex.com</web>
// <license>
// The MIT License (MIT)
// 
// Copyright (c) 2013 Marc Plessis
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// 
// </license>
#endregion
#region using

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using Database.POCO;
using GalaSoft.MvvmLight.CommandWpf;
using Helpers.Class;
using Helpers.Contracts;
using Interfaces.Enums;
using SampleModule.Class;
using SampleModule.ViewModels.Controls;

#endregion

namespace SampleModule.ViewModels
{
    [Module("AppelsLocalized", 1, "09a02d29-d7cb-4efd-a144-4165e7024c04", typeof(AccueilAppelsViewModel), TypeModulesEnum.Appels, "LoadDatas")]
    public class AccueilAppelsViewModel : ViewModelBaseModule
    {
        private bool _isLoading;

        #region properties

        private List<AppelWithPersonnes> _appels;
        public List<AppelWithPersonnes> Appels
        {
            get { return _appels; }
            set
            {
                _appels = value;
                RaisePropertyChanged(() => Appels);
            }
        }

        private string _titleAppels;
        public string TitleAppels
        {
            get { return _titleAppels; }
            set
            {
                _titleAppels = value;
                RaisePropertyChanged(() => TitleAppels);
            }
        }

        private List<SysUtilisateur> _personnes;
        public List<SysUtilisateur> Personnes
        {
            get { return _personnes; }
            set
            {
                _personnes = value;
                RaisePropertyChanged(() => Personnes);
            }
        }

        private SysUtilisateur _selectedUtilisateur;
        public SysUtilisateur SelectedUtilisateur
        {
            get { return _selectedUtilisateur; }
            set
            {
                _selectedUtilisateur = value;
                if (!_isLoading)
                {
                    LoadDatas();   
                }
                RaisePropertyChanged(() => SelectedUtilisateur);
            }
        }

        private AppelWithPersonnes _selectedAppel;
        public AppelWithPersonnes SelectedAppel
        {
            get { return _selectedAppel; }
            set
            {
                _selectedAppel = value;
                if (value != null)
                {
                    Services.NavigationService.NavigateTo<CreateOrUpdateAppelViewModel>(this, new object[] { value.Appel.ID }, true);
                }
                RaisePropertyChanged(() => SelectedAppel);
            }
        }

        private DateTime _name;
        public DateTime Name
        {
            get { return _name; }
            set
            {
                _name = value;
                RaisePropertyChanged(() => Name);
            }
        }
        private List<DateTime> _moisAnnees;
        public List<DateTime> MoisAnnees
        {
            get { return _moisAnnees; }
            set
            {
                _moisAnnees = value;
                RaisePropertyChanged(() => MoisAnnees);
            }
        }

        private DateTime _selectedMonthYear;
        public DateTime SelectedMonthYear
        {
            get { return _selectedMonthYear; }
            set
            {
                _selectedMonthYear = value;
                if (!_isLoading)
                {
                    LoadDatas();
                }
                RaisePropertyChanged(() => SelectedMonthYear);
            }
        }

        private bool _isLoadAppels;
        public bool IsLoadAppels
        {
            get { return _isLoadAppels; }
            set
            {
                _isLoadAppels = value;
                RaisePropertyChanged(() => IsLoadAppels);
            }
        }

        private int _totalAppels;
        public int TotalAppels
        {
            get { return _totalAppels; }
            set
            {
                _totalAppels = value;
                RaisePropertyChanged(() => TotalAppels);
            }
        }

        public ObservableCollection<PersonAppelsForStats> PersonnesAppels { get; set; }
        public RelayCommand CreateAppelCommand { get; set; }
        public RelayCommand<AppelWithPersonnes> DeleteCommand { get; set; }
        #endregion

        public AccueilAppelsViewModel()
        {
            _isLoading = true;

            PersonnesAppels = new ObservableCollection<PersonAppelsForStats>();
            CreateAppelCommand = new RelayCommand(CreateAppel, CanCreateAppel);
            DeleteCommand = new RelayCommand<AppelWithPersonnes>(DeleteAppel, CanDeleteAppel);

            LoadMonthYear();
            SelectedMonthYear = MoisAnnees.First();

            Personnes = new List<SysUtilisateur>
                        {
                            new SysUtilisateur {Code = "TOUS", Nom = Services.LocalizedService.LocalizedFromKey("AccueilAppels_FiltresTousPersonnes"), ID = 0}
                        };
            Personnes.AddRange(Services.DatabaseService.Service.GetAll<SysUtilisateur>().ToList());

            ValueRightsEnum rights;
            bool viewAlls = false;
            if (Services.AccessControlService.IsAuthorizedFunction(Services.RightsService.GetIdentifiantRight((int)RightsEnum.ViewAllAppels, TypeModulesEnum.Appels), out rights))
            {
                viewAlls = rights.HasFlag(ValueRightsEnum.Tous);
            }
            SelectedUtilisateur = !viewAlls ? Personnes.First(p => p.ID == Services.AccessControlService.CurrentUser.ID) : Personnes.First();
            PersonnesAppels = new ObservableCollection<PersonAppelsForStats>();

            _isLoading = false;

            Services.MessageBarreEtatService.SetContentFree(new OpenSampleControlBarreViewModel());
        }

        #region relaycommand

        private bool CanCreateAppel()
        {
            ValueRightsEnum rights;
            if (Services.AccessControlService.IsAuthorizedFunction(Services.RightsService.GetIdentifiantRight((int)RightsEnum.Appel, TypeModulesEnum.Appels), out rights))
            {
                return rights.HasFlag(ValueRightsEnum.Modification);
            }
            return false;
        }

        private void CreateAppel()
        {
            Services.NavigationService.NavigateTo<CreateOrUpdateAppelViewModel>(this, new object[] { new SampleAppel() }, true);
        }

        private bool CanDeleteAppel(AppelWithPersonnes arg)
        {
            ValueRightsEnum rights;
            if (Services.AccessControlService.IsAuthorizedFunction(Services.RightsService.GetIdentifiantRight((int)RightsEnum.Appel, TypeModulesEnum.Appels), out rights))
            {
                return rights.HasFlag(ValueRightsEnum.Suppression);
            }
            return false;
        }

        private void DeleteAppel(AppelWithPersonnes obj)
        {
            Services.ChildWindowService.QuestionMessage(Services.LocalizedService.LocalizedFromKey("AccueilAppels_SupprimerQuestion"), Services.LocalizedService.LocalizedFromKey("MainCoreTitle"), OnDeleteAppel, obj);
        }

        #endregion

        #region events
        
        private void OnDeleteAppel(AnswerQuestionMessageEnum arg1, object[] arg2)
        {
            if (arg1 == AnswerQuestionMessageEnum.Yes)
            {
                var appel = (AppelWithPersonnes)arg2[0];
                Services.DatabaseService.Service.Delete<SampleAppelCommentaires>(a => a.Appel.ID == appel.Appel.ID, true);
                Services.DatabaseService.Service.Delete<SampleAppelUtilisateurs>(a => a.Appel.ID == appel.Appel.ID, true);
                Services.DatabaseService.Service.Delete<SampleAppel>(appel.Appel, true);

                LoadDatas();
            }
        }

        #endregion

        #region private

        private void LoadDatas()
        {
            Services.MessageBarreEtatService.SetMessage(Services.LocalizedService.LocalizedFromKey("AccueilAppels_Chargement"), IconBarreEtatEnum.Wait);

            IsLoadAppels = true;
            var workerJours = new BackgroundWorker
            {
                WorkerReportsProgress = true
            };

            workerJours.DoWork += (s, ex) => LoadAppels(ex);
            workerJours.RunWorkerAsync();
            workerJours.RunWorkerCompleted += (sender, args) =>
            {
                Services.MessageBarreEtatService.ClearMessage();

                IsLoadAppels = false;
                Appels = (List<AppelWithPersonnes>)args.Result;

                //Chargement des personnes
                ValueRightsEnum rights;
                bool viewAlls = false;
                if (Services.AccessControlService.IsAuthorizedFunction(Services.RightsService.GetIdentifiantRight((int)RightsEnum.ViewAllAppels, TypeModulesEnum.Appels), out rights))
                {
                    viewAlls = rights.HasFlag(ValueRightsEnum.Tous);
                }
                if (viewAlls)
                {
                    //Pour le graphique
                    PersonnesAppels.Clear();
                    foreach (var appel in Appels)
                    {
                        AppelWithPersonnes appel1 = appel;
                        var personnes =
                            Services.DatabaseService.Service.Where<SampleAppelUtilisateurs>(a => a.Appel.ID == appel1.Appel.ID);
                        foreach (var personne in personnes)
                        {
                            if (personne.Destinataire != null)
                            {
                                if (PersonnesAppels.Any(p => p.Personne == personne.Destinataire))
                                {
                                    PersonnesAppels.First(p => p.Personne == personne.Destinataire).NumberAppel += 1;
                                }
                                else
                                {
                                    PersonnesAppels.Add(new PersonAppelsForStats { Personne = personne.Destinataire, NumberAppel = 1 });
                                }
                            }
                        }
                    }

                    TotalAppels = PersonnesAppels.Sum(p => p.NumberAppel);
                }
            };
        }

        /// <summary>
        /// On charge les mois avec 1 an en arriere
        /// </summary>
        private void LoadMonthYear()
        {
            MoisAnnees = new List<DateTime>();
            var dateCurrent = DateTime.Today;
            for (int i = 0; i <= 12; i++)
            {
                var newDate = dateCurrent.AddMonths(-i);
                MoisAnnees.Add(DateTime.Parse(string.Format("01/{0}/{1}", newDate.Month, newDate.Year)));
            }
            MoisAnnees = MoisAnnees.OrderByDescending(n => n.Date).ToList();
        }

        private void LoadAppels(DoWorkEventArgs ex)
        {
            var appelsFound = new List<SampleAppel>();
            if (SelectedMonthYear != DateTime.MinValue && SelectedUtilisateur != null)
            {
                ValueRightsEnum rights;
                bool viewAlls = false;
                if (Services.AccessControlService.IsAuthorizedFunction(Services.RightsService.GetIdentifiantRight((int)RightsEnum.ViewAllAppels, TypeModulesEnum.Appels), out rights))
                {
                    viewAlls = rights.HasFlag(ValueRightsEnum.Tous);
                }

                if (viewAlls)
                {
                    if (Services.DatabaseService.Service.Any<SampleAppel>())
                    {
                        appelsFound =
                            Services.DatabaseService.Service.Where<SampleAppel>(
                                a =>
                                    a.SysDateCreation.Month == SelectedMonthYear.Month &&
                                    a.SysDateCreation.Year == SelectedMonthYear.Year).ToList();
                    }
                    TitleAppels = Services.LocalizedService.LocalizedFromKey("Accueil_DerniersAppels", true);
                }
                else
                {
                    var id = Services.AccessControlService.CurrentUser.ID;
                    var appelsUser = Services.DatabaseService.Service.Where<SampleAppelUtilisateurs>(a => a.Destinataire.ID == id);
                    if (Services.DatabaseService.Service.Any<SampleAppel>())
                    {
                        var appels =
                            Services.DatabaseService.Service.Where<SampleAppel>(
                                a =>
                                    a.SysDateCreation.Month == SelectedMonthYear.Month &&
                                    a.SysDateCreation.Year == SelectedMonthYear.Year).ToList();
                        foreach (var utilisateur in appelsUser)
                        {
                            appelsFound.AddRange(appels.Where(a => a.ID == utilisateur.Appel.ID));
                        }
                    }
                    TitleAppels = Services.LocalizedService.LocalizedFromKey("Accueil_MesAppels", true);
                }

                if (SelectedUtilisateur != null)
                {
                    if (SelectedUtilisateur.ID == 0 || SelectedUtilisateur == Services.AccessControlService.CurrentUser)
                    {
                        //Tous
                        ex.Result = CreateCollectionAppelWithPersonnes(appelsFound);
                    }
                    else
                    {
                        var id = SelectedUtilisateur.ID;
                        var appelsUser = Services.DatabaseService.Service.Where<SampleAppelUtilisateurs>(a => a.Destinataire.ID == id);
                        var appels = new List<SampleAppel>();
                        foreach (var utilisateur in appelsUser)
                        {
                            appels.AddRange(appelsFound.Where(a => a.ID == utilisateur.Appel.ID));
                        }
                        ex.Result = CreateCollectionAppelWithPersonnes(appels);
                    }
                }
                else
                {
                    ex.Result = CreateCollectionAppelWithPersonnes(appelsFound);
                }
            }
            else
            {
                ex.Result = new List<AppelWithPersonnes>();   
            }
        }

        private List<AppelWithPersonnes> CreateCollectionAppelWithPersonnes(IEnumerable<SampleAppel> appels)
        {
            var list = new List<AppelWithPersonnes>();
            foreach (var appel in appels.OrderByDescending(a => a.SysDateCreation))
            {
                var appelWithPerson = new AppelWithPersonnes {Appel = appel, Personnes = new List<SysUtilisateur>()};

                SampleAppel appel1 = appel;
                var personnes = Services.DatabaseService.Service.Where<SampleAppelUtilisateurs>(a => a.Appel.ID == appel1.ID);
                foreach (var personne in personnes)
                {
                    appelWithPerson.Personnes.Add(personne.Destinataire);
                }

                list.Add(appelWithPerson);
            }
            return list;
        }

        #endregion
    }
}
